/**
 * 
 */
package model.persistence.mysql;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

import model.core.torneo.Classifica;
import model.core.torneo.Commissione;
import model.core.torneo.Gara;
import model.core.torneo.Torneo;
import model.core.utente.Commissario;
import model.core.utente.Giocatore;
import model.core.utente.GiocatoreInterface;
import model.core.utente.Squadra;
import model.persistence.TorneoDAO;

/**
 * @author Giuseppe Fusco (fusgius19@gmail.com)
 *
 */
public class TorneoDAO_MySQL extends MySQLDomainDAO implements TorneoDAO{

	/**
	 * @param dbms
	 * @throws SQLException 
	 */
	public TorneoDAO_MySQL(MySQLDBMS dbms) throws SQLException {
		super(dbms);
		// TODO Auto-generated constructor stub
	}

	/* (non-Javadoc)
	 * @see model.facade.persistence.PersistenceCommand#insert(java.lang.Object)
	 */
	@Override
	public boolean insert(Object...obj) {
		// TODO Auto-generated method stub
		if(obj[0] instanceof Torneo){
			try {
				synchronized (obj[0]) {
					Torneo t = (Torneo)obj[0];
					PreparedStatement p = mys.getPreparedStatement("insert into torneo(nome,tipologia,numero_edizione,anno_svolgimento" +
							",is_singolo,stato_torneo,vincitore,max_partecipanti,min_partecipanti) values(?,?,?,?,?,?,?,?,?)");
					p.setString(1, t.getNome());
					p.setString(2, t.getTipologia());
					p.setInt(3, t.getNumero_edizione());
					p.setInt(4, t.getAnno_svolgimento());
					p.setInt(5, t.isSingolo()?1:0);
					p.setString(6, t.getStato());
					int vin = MySQLUtentiQueryUtility.getIdGiocatore(t.getVincitore(), mys);
					if(vin!=-1)p.setInt(7, vin);
					else p.setNull(7, java.sql.Types.NULL);
					p.setInt(8, t.getMaxComponenti());
					p.setInt(9, t.getMinComponenti());
					p.execute();
					p.close();
					int tid = MySQLTorneiQueryUtility.getIdTorneoByNome(t.getNome(), mys);
					if(tid!=-1){
						for(GiocatoreInterface g: t.getClassifica().getGiocatori()){
							addGiocatoreToTorneo(g, t);
						}
						for(Commissario com: t.getCommissione().getCommissione()){
							addCommissarioToTorneo(com, t);
						}
						return insertCalendario(t);
					}
					else
						return false;	
				}
			} catch (Exception e) {
				// TODO: handle exception
				return false;
			}
		}
		else
			return false;
	}

	/* (non-Javadoc)
	 * @see model.facade.persistence.PersistenceCommand#delete(java.lang.Object)
	 */
	@Override
	public boolean delete(Object obj) {
		// TODO Auto-generated method stub
		if(obj instanceof Gara){
			Torneo g = (Torneo)obj;
			try {
				mys.executeUpdate("delete from torneo where nome=\""+g.getNome()+"\"");
				return true;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
		}else return false;
	}

	/* (non-Javadoc)
	 * @see model.facade.persistence.PersistenceCommand#update(java.lang.Object)
	 */
	@Override
	public boolean update(Object obj) {
		// TODO Auto-generated method stub
		if(obj instanceof Torneo){
			try {
				synchronized (obj) {
					Torneo t = (Torneo)obj;
					ResultSet r = mys.getResult("select * from torneo where nome=\""+t.getNome()+"\"");
					if(r.first()){
						r.updateString("nome", t.getNome());
						r.updateInt("numero_edizione", t.getNumero_edizione());
						r.updateInt("anno_svolgimento", t.getAnno_svolgimento());
						r.updateString("tipologia", t.getTipologia());
						r.updateString("stato_torneo", t.getStato());
						r.updateInt("is_singolo", t.isSingolo()?1:0);
						r.updateInt("max_partecipanti", t.getClassifica().getMaxComponenti());
						r.updateInt("min_partecipanti", t.getClassifica().getMinComponenti());
						int idvin = MySQLUtentiQueryUtility.getIdGiocatore(t.getVincitore(), mys);
						if(idvin!=-1)r.updateInt("vincitore", idvin);
						else r.updateNull("vincitore");
						r.updateRow();
						r.close();
						return true;
					}else
						return false;	
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
		}else
			return false;
	}

	/* (non-Javadoc)
	 * @see model.facade.persistence.PersistenceCommand#retrieve(java.lang.Object[])
	 */
	@Override
	public Object retrieve(Object... properties) {
		// TODO Auto-generated method stub
		if(properties.length==1 && properties[0] instanceof String){
			Torneo t = MySQLTorneiQueryUtility.getTorneoByNome((String) properties[0], mys);
			t.setClassifica(getClassificaByTorneo(t));
			t.setCalendario(getCalendarioByTorneo(t));
			t.setCommissione(getCommissioneByTorneo(t));
			return t;
		}else
			return null;
	}

	public void removeCommissarioFromTorneo(Commissario co, Torneo torneo) throws SQLException{
		int id = MySQLUtentiQueryUtility.getIdStudente(co.getMatricola(), co.getPassword(), mys);
		mys.executeUpdate("delete from commissione where (torneo="+MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys)+" and commissario="+id+")");
		mys.executeUpdate("update studente set tipo=\"STUDENTE\" where idstudente="+id);
	}

	public void addCommissarioToTorneo(Commissario co, Torneo torneo) throws SQLException{
		mys.executeUpdate("insert into commissione(torneo,commissario) values("+MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys)+","+MySQLUtentiQueryUtility.getIdStudente(co.getMatricola(), co.getPassword(), mys)+")");
		mys.executeUpdate("update studente set tipo=\"COMMISSARIO\" where idstudente="+MySQLUtentiQueryUtility.getIdStudente(co.getMatricola(), co.getPassword(), mys));
	}

	public void addGiocatoreToTorneo(GiocatoreInterface gi, Torneo torneo) throws SQLException{
		MySQLTorneiQueryUtility.insertPartecipanteTorneo(gi, torneo, mys);
	}

	public void removeGiocatoreFromTorneo(GiocatoreInterface gi, Torneo torneo) throws SQLException{
		mys.executeUpdate("delete from giocatore where (torneo="+MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys)+" and idgiocatore="+
				((gi instanceof Giocatore)?
						MySQLUtentiQueryUtility.getIdGiocatorebyIdStudente((Giocatore) gi, mys):
							MySQLUtentiQueryUtility.getIdSquadraByNome(((Squadra)gi).getNome(), mys)
						)+")");
	}

	public Classifica getClassificaByTorneo(Torneo torneo){
		int tid = MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys);
		if(tid!=-1){
			try {
				ResultSet rt = mys.getResult("select max_partecipanti,min_partecipanti, is_singolo from torneo where idtorneo="+tid);
				if(rt.first()){
					Classifica c = new Classifica(rt.getInt(1), rt.getInt(2));
					ResultSet r = mys.getResult("select * from giocatore where torneo="+tid);
					while(r.next()){
						c.addGiocatore(MySQLUtentiQueryUtility.getGiocatoreByIdGiocatore(r.getInt("giocatore"), mys), rt.getInt(3)==1?true:false);
					}
					return c;
				}
				else
					return null;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				return null;
			}
		}else
			return null;
	}

	public Commissione getCommissioneByTorneo(Torneo torneo){
		int tid = MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys);
		if(tid!=-1){
			try {
				Commissione c = new Commissione();
				ResultSet r = mys.getResult("select * from commissione where torneo="+tid);
				while(r.next()){
					c.addCommissario((Commissario) MySQLUtentiQueryUtility.getStudenteByIdStudente(r.getInt("commissario"), mys));
				}
				return c;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				return null;
			}
		}else
			return null;
	}

	public List<Gara> getCalendarioByTorneo(Torneo torneo){
		int tid = MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys);
		if(tid!=-1){
			try {
				List<Gara> gare = new ArrayList<Gara>();
				ResultSet r = mys.getResult("select * from gara where torneo="+tid);
				while(r.next()){
					gare.add(MySQLTorneiQueryUtility.getGaraById(r.getInt("idgara"), mys));
				}
				return gare;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				return null;
			}
		}else
			return null;
	}

	public boolean insertCalendario(Torneo torneo){
		try {
			int tid = MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys);
			PreparedStatement p = mys.getPreparedStatement("insert into gara(torneo,nro_giorni_da_disputare,data_inizio,data_fine,is_sync,stato_gara,vincitore,arbitro) values(?,?,?,?,?,?,?,?)");
			for(Gara g: torneo.getCalendario()){
				p.setInt(1, tid);
				p.setInt(2, g.getNro_giorni_da_disputare());
				p.setTimestamp(3, new Timestamp(g.getData_inizio().getTimeInMillis()));
				p.setTimestamp(4, new Timestamp(g.getData_fine().getTimeInMillis()));
				p.setInt(5, g.isSync()?1:0);
				p.setString(6, g.getStato());
				int idvin = MySQLUtentiQueryUtility.getIdGiocatore(g.getVincitore(), mys);
				if(idvin!=-1)p.setInt(7, idvin);
				else p.setNull(7, Types.NULL);
				int st = MySQLUtentiQueryUtility.getIdStudente(g.getArbitro().getMatricola(), g.getArbitro().getPassword(), mys);
				if(st!=-1) p.setInt(8, st);
				else p.setNull(8, Types.NULL);
				p.execute();
			}
			p.close();
			List<Gara> cal = torneo.getCalendario();
			int i=0;
			ResultSet res = mys.getResult("select idgara from gara where torneo="+tid);
			while(res.next()){
				insertPartecipanteToGara(cal.get(i++).getGiocatori(), res.getInt("idgara"), mys);
			}
			return true;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	public List<Torneo> load(String text) throws SQLException{
		List<Torneo> list = new ArrayList<Torneo>();
		ResultSet r = mys.getResult("select * from torneo where (nome like\"%"+text+"%\" or tipologia like\"%"+text+"%\" or " +
				"numero_edizione like\"%"+text+"%\" or anno_svolgimento like\"%"+text+"%\" or stato_torneo like\"%"+text+"%\" or max_partecipanti like\"%"+text+"%\" or " +
				"min_partecipanti like\"%"+text+"%\")");
		while(r.next()){
			list.add((Torneo) retrieve(r.getString("nome")));
		}
		r.close();
		return list;
	}

	public boolean deleteCalendario(Torneo torneo){
		try {
			mys.executeUpdate("delete from gara where torneo="+MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys));
			return true;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
	
	public boolean deleteCommissione(Torneo torneo){
		try {
			mys.executeUpdate("delete from commissione where torneo="+MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys));
			return true;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
	
	public boolean deleteClassifica(Torneo torneo){
		try {
			mys.executeUpdate("delete from giocatore where torneo="+MySQLTorneiQueryUtility.getIdTorneoByNome(torneo.getNome(), mys));
			return true;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	private boolean insertPartecipanteToGara(List<GiocatoreInterface> part, int idgara, MySQLDBMS mys){
		ResultSet r;
		try {
			r = mys.getResult("select idgara from gara where idgara="+idgara);
			if(r.first()){
				for(GiocatoreInterface g: part){
					if(MySQLUtentiQueryUtility.getIdGiocatore(g, mys)==-1)
						return false;
				}
				for(GiocatoreInterface g: part){
					mys.executeUpdate("insert into partecipanti_gara(gara,giocatore) values("+idgara+","+
							MySQLUtentiQueryUtility.getIdGiocatore(g, mys)+")");
				}
				r.close();
				return true;
			}else
				return false;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
}
